package com.tianheng.wanzhou.datacollecting.netty.cushaji;

import com.tianheng.wanzhou.datacollecting.util.CRC16Util;
import com.tianheng.wanzhou.datacollecting.util.StrUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.ReferenceCountUtil;

import java.util.List;

/**
 * @author MrZeyu
 * @Email MrZeyu@126.com
 * @Date 2019/3/28 13:07,星期四
 */
public class GatherDecoder extends ByteToMessageDecoder {
    /**
     *  数据之前的指令头长度 21
     * 固定头 2      9D D9
     * 时间戳 4      5b a4 9f ee
     * 企业编号 2    00 01
     * 车间编号 2    00 01
     * 设备型号 1    01
     * 设备编号 4    00 00 00 01
     * 数据长度 4    00 00 00 0A
     * 功能代码 1    F1
     * 子功能代码1   01
     */
    private static final int HEAD_LENGTH = 21;
    /**
     *  功能代码位置
     */
    private static final int FUN_ID_SITE = 19;
    /**
     *  子功能代码位置
     */
    private static final int CHILD_FUN_ID_SITE = 20;
    /**
     *  功能代码
     */
     private static final byte[][] FUN_ID_ARR = {

             {(byte)0x1F,(byte)0x01},//轴库库位状态
             {(byte)0x1F,(byte)0x02},
             {(byte)0x1F,(byte)0x03},//人员名单及入库
             {(byte)0x1F,(byte)0x06},//出库
             {(byte)0x1F,(byte)0x07},//瑕疵点
             {(byte)0x1F,(byte)0x08},//1-45号布号
             {(byte)0x1F,(byte)0x09}//46-90号布号

     };
    /**
     *  七区长度
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
        //创建字节数组,buffer.readableBytes可读字节长度
        if(buffer.readableBytes()<HEAD_LENGTH){
            return;
        }
        int startIndex = getNewStartIndex(buffer);
        if(startIndex!=0){
            //System.out.println("去除字节数"+startIndex);
            //9DD9不在首位,则去除在其前面的字节，然后，重新进入
            clearByteBeforeAndReIn(ctx,buffer,out,startIndex);
            return;
        }else{
            byte[] copyArray = new byte[HEAD_LENGTH];
            //复制内容到字节数组b
            ByteBuf bufferCopy = buffer.copy(0,HEAD_LENGTH);
            bufferCopy.readBytes(copyArray);
            ReferenceCountUtil.release(bufferCopy);
            //获取功能代码和子功能代码，除了允许的功能代码，之外的直接清掉
            if(!inArray(copyArray)){
                clearByteBeforeAndReIn(ctx,buffer,out,HEAD_LENGTH-1);
                return;
            }

            //获取数据区长度
            int dataLength = StrUtil.getDataLength(copyArray,15);

            //可读字节长度不足，则返回等待
            if(buffer.readableBytes()<HEAD_LENGTH+dataLength-2){
                return;
            }

            //可读字节长度够，则转换输出
            byte[] b = new byte[HEAD_LENGTH+dataLength-2];
            buffer.readBytes(b,0,HEAD_LENGTH+dataLength-2);
            buffer.discardReadBytes();

            int byteLen=b.length;//数组长度
            //校验位
            int check = CRC16Util.calcCrc16(b,0,byteLen-2);


            byte[] crc = new byte[2];
            crc[0] = (byte)(check & 0xff);//低8位
            crc[1] = (byte)((check >> 8) & 0xff);//高8位

            //进行CRC校验判断
              if( crc[0]==b[byteLen-1] && crc[1]==b[byteLen-2]){
                out.add(StrUtil.bytesToHexString(b));
            }else{
                return;
            }
        }
    }


    /**
     *  清除9DD9前的,并重新递归进入
     */
    private void clearByteBeforeAndReIn(ChannelHandlerContext ctx,ByteBuf buffer,List<Object> out,int startIndex)throws Exception{
        byte[] b = new byte[HEAD_LENGTH];
        buffer.readBytes(b,0,startIndex);
        buffer.discardReadBytes();
        //递归，重新开始
        decode(ctx,buffer,out);
    }

    /**
     * 找到9DD9的位置下标
     */
    private int getNewStartIndex(ByteBuf buffer){
        byte[] copyArray = new byte[HEAD_LENGTH];
        //复制内容到字节数组b
        ByteBuf bufferCopy = buffer.copy(0,HEAD_LENGTH);
        bufferCopy.readBytes(copyArray);
        ReferenceCountUtil.release(bufferCopy);
        int startIndex = copyArray.length-1;
        for(int i=0;i<copyArray.length;i++){
            if(i<copyArray.length-1 && copyArray[i]==(byte)0x9D && copyArray[i+1]==(byte)0xD9){
                startIndex = i;
                break;
            }
        }
        return startIndex;

    }
    /**
     * 判断功能代码是否在允许范围内
     */
    private boolean inArray(byte[] buffer){
        for(int i=0;i<FUN_ID_ARR.length;i++){
            //判断功能代码是否一致
            if( buffer[FUN_ID_SITE]==FUN_ID_ARR[i][0] && buffer[CHILD_FUN_ID_SITE]==FUN_ID_ARR[i][1]){
                return true;

            }
        }
        return false;
    }


}
